from asyncio import get_event_loop, sleep, wait
from base64 import b64encode, b64decode
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.utils import formataddr
from os import system
from sys import exit
from os.path import exists
from os import remove
from platform import system as plt_system
from smtplib import SMTP_SSL
from time import strftime, localtime
from msvcrt import getch, putch
from database_util import db_update
from datetime import datetime

try:
    from pyppeteer import launch
    from pyppeteer import launcher
except ModuleNotFoundError:
    print('安装pyppeteer')
    res = ''
    if plt_system() == 'Windows':
        res = system('pip install pyppeteer')
    elif plt_system() == 'Linux':
        from platform import linux_distribution

        res = system('pip3 install pyppeteer')
        linux_release = linux_distribution()[0]
        command = ''
        if linux_release.__contains__('CentOS'):
            command = '''
            sudo yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc
            '''
        elif linux_release.__contains__('Ubuntu'):
            command = '''
            sudo apt-get install gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
            '''
        system(command)
    if res != 0:
        print('模块安装失败！')
        exit(1)
    from pyppeteer import launch
    from pyppeteer import launcher

launcher.DEFAULT_ARGS.remove('--enable-automation')
launcher.DEFAULT_ARGS.append('--disable-web-security')

header = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Cache-Control': 'max-age=0',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
}

'''
status
0: 未登录
1: 已登录

time_for_wait：循环等待时间
timeout：超时等待时间
'''
status = 0
date_today, time_today = strftime("%Y-%m-%d %H:%M:%S", localtime()).split(' ')
time_for_wait = 1200
timeout = 25

my_sender = '发件人邮箱账号'
my_pass = '发件人邮箱密码(当时申请smtp给的口令)'


def getpass():
    li = []
    while True:
        ch = getch()
        # 回车
        if ch == b'\r':
            putch(b'\n')
            real_pass = b''.join(li).decode()
            return real_pass
        # 退格
        elif ch == b'\x08':
            if li:
                li.pop()
                putch(b'\b')
                putch(b' ')
                putch(b'\b')
        # Esc
        elif ch == b'\x1b':
            continue
        else:
            li.append(ch)
            putch(b'*')


def load_img(file, img_id):
    if exists(file):
        with open(file=file, mode='rb') as img:
            msg_image = MIMEImage(img.read())
            msg_image.add_header('Content-ID', img_id)
            return msg_image


def remove_img(file):
    if exists(file):
        remove(file)
        print('成功删除文件:', file)
    else:
        print('未找到此文件:', file)


def mail_send_with_user(content, subject, sender, getter, img):
    global my_pass

    try:
        msg_text = MIMEText(str(content), "html", "utf-8")
        msg = MIMEMultipart('related')
        msg.attach(msg_text)
        msg.attach(load_img(img + '.png', img))
        msg['From'] = formataddr([sender, sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
        msg['Subject'] = subject

        server = SMTP_SSL("smtp.qq.com", 465)
        server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱密码

        msg['To'] = formataddr([getter, getter])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
        server.sendmail(my_sender, getter, msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
        server.quit()
        print(">>> 《%s》 发送成功" % subject, strftime("%Y-%m-%d %H:%M:%S", localtime()))
        return True
    except Exception as e:
        print(e)
        return False


async def wait_for_navigation(page, events):
    await wait([
        events,
        page.waitForNavigation({'timeout': timeout * 1000})
    ])


async def main(user_id, username, password, email):
    global status, timeout, res


    # 初始化浏览器
    browser = await launch(headless=False, args=['--start-maximized'])
    # 无痕模式
    # browser = await browser.createIncogniteBrowserContext()
    try:
        # 登录
        print('>>> 开启浏览器')
        page = await browser.newPage()

        await page.setViewport({'width': 1366, 'height': 768})
        await page.setExtraHTTPHeaders(headers=header)
        await page.goto('https://idas.uestc.edu.cn/authserver/login', {'timeout': 1000 * timeout})
        await page.evaluate(
            '''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => none } }) }''')
        flag = True
        await wait([
            page.waitForNavigation({'timeout': timeout * 1000})
        ])

        # 如果已登录，则跳过
        if page.url != 'https://idas.uestc.edu.cn/authserver/login':
            status = 1
            flag = False

        if flag:
            await wait([
                page.waitForNavigation({'timeout': timeout * 1000})
            ])
            await page.type('#username', username)
            await page.type('#password', b64decode(password).decode())
            await page.click('.auth_login_btn')
            await sleep(1)

            # 跳过滑动验证模块
            # await page.evaluate(
            #     '''
            #     () => {
            #         $("#captcha-id").empty();
            #         var casLoginForm = $("#casLoginForm");
            #         casLoginForm.submit();
            #     }
            #     '''
            # )

            # 模拟滑动滑块
            iframe = await page.J('.slider')
            box = await page.querySelector('.slider')
            box = await box.boundingBox()

            while iframe:
                await iframe.hover()
                await page.mouse.down()
                await page.mouse.move(box['x'] + 280 / 2, box['y'])
                await page.mouse.up()
                await sleep(3)
                iframe = await page.J('.slider')

            # 等待10s登录
            while page.url != 'https://eportal.uestc.edu.cn/new/index.html' and page.url != 'https://idas.uestc.edu.cn/authserver/index.do':
                await sleep(10)
                print('>>> 用户未登录!', strftime("%Y-%m-%d %H:%M:%S", localtime()))
            if page.url == 'https://eportal.uestc.edu.cn/new/index.html' or page.url == 'https://idas.uestc.edu.cn/authserver/index.do':
                status = 1
                print(">>> 已登录！", strftime("%Y-%m-%d %H:%M:%S", localtime()))

        if status == 1:
            # 登录成功，跳转到健康填报界面
            await page.goto(
                'https://eportal.uestc.edu.cn/jkdkapp/sys/lwReportEpidemicStu/*default/index.do#/add',
                {'timeout': 1000 * timeout})

            count = 0
            await sleep(5)
            await page.waitForSelector('button', {'timeout': 1000 * timeout})
            button = await page.querySelectorAll('button')
            while page.url != 'https://eportal.uestc.edu.cn/jkdkapp/sys/lwReportEpidemicStu/*default/index.do#/add' and button is []:
                count += 1
                await sleep(3)
                button = await page.querySelectorAll('button')
                # 大于三次 重新加载
                if count > 3:
                    await page.goto(
                        'https://eportal.uestc.edu.cn/jkdkapp/sys/lwReportEpidemicStu/*default/index.do#/add')
                    count = 0

            print('>>> 进入填报信息界面')
            await button[len(button) - 1].click()
            while await page.querySelector('.mint-msgbox-btn.mint-msgbox-confirm.mt-btn-primary') is None:
                await sleep(3)
                await button[len(button) - 1].click()
            await page.click('.mint-msgbox-btn.mint-msgbox-confirm.mt-btn-primary')
            print('>>> 提交信息！')

            # 提交后，回到信息填报记录界面，检测是否填报成功
            await sleep(3)
            await page.goto(
                'https://eportal.uestc.edu.cn/jkdkapp/sys/lwReportEpidemicStu/index.do#/dailyReport',
                {'timeout': 1000 * timeout})

            count = 0
            await sleep(3)
            button = await page.querySelectorAll('.bh-btn.bh-btn-primary')
            while len(button) < 3:
                count += 1
                button = await page.querySelectorAll('.bh-btn.bh-btn-primary')
                await sleep(3)
                if count > 3:
                    await page.reload({'timeout': 1000 * timeout})

            await button[2].click()
            await sleep(1)
            # 填报结果查询
            result = await page.waitForSelector('.bh-modal', {'timeout': 1000 * timeout})
            await result.screenshot({'path': 'result.png'})
            content = await page.querySelector('.content')
            content = await content.getProperty('textContent')
            info = await content.jsonValue()

            print('**************', info, strftime("%Y-%m-%d %H:%M:%S", localtime()), '**************')
            if info.__contains__('今日已填报'):
                while not exists('result.png'):
                    await sleep(3)
                    result.screenshot({'path': 'result.png'})

                # 发送结果截图到邮箱
                content = '''
                <div class="result">
                    <div class="info">填报结果如下：</div>
                    <div><img src="cid:result" width="100%"></div>
                </div>
                '''
                if mail_send_with_user(content, '健康填报结果：今日已填报', my_sender, email, 'result'):
                    remove('result.png')
                db_update('''
                    update db_uestc.daily_report
                    set send_date = '%s'
                    where user_id = %s;
                    ''' % (datetime.now().strftime("%Y-%m-%d"), user_id))
                res = True
            else:
                res = False
    except Exception as e:
        print(e)
    finally:
        await browser.close()
        return res


def start(user_id, stu_num, password, email):
    get_event_loop().run_until_complete(main(user_id, stu_num, password, email))


if __name__ == '__main__':
    try:
        print('**************UESTC自动每日健康填报程序**************')
        get_event_loop().run_until_complete(main())
    except Exception as e:
        print(e)
        system("python daily_report_auto.py")
    finally:
        input('> 按任意键退出')
